package com.xiaotu.spider.mgtv.pageprocessor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.selector.Html;

import com.xiaotu.common.exception.SpiderException;
import com.xiaotu.common.exception.SpiderExceptionCode;
import com.xiaotu.common.model.TVPubCommentModel;
import com.xiaotu.common.model.TVRecordModel;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.HtmlUtil;
import com.xiaotu.common.util.KeywordEncode;
import com.xiaotu.common.util.PageUtils;
import com.xiaotu.common.util.RegexUtils;
import com.xiaotu.common.util.SepratorUtil;
import com.xiaotu.common.util.StringUtil;
import com.xiaotu.common.util.TVProcessUtils;
import com.xiaotu.spider.APageProcessor;

/**
 * 爬取芒果tv相关信息类
 */
@Component("MGTVPageProcessor")
@Scope("prototype")
public class MGTVPageProcessor extends APageProcessor
{

    public static final String DETAIL_PLAYTOTALNUMBER =
            "http://videocenter-2039197532.cn-north-1.elb.amazonaws.com.cn/dynamicinfo?cid=";

    public static final String PLAY_PLAYTOTALNUMBER =
            "http://videocenter-2039197532.cn-north-1.elb.amazonaws.com.cn/dynamicinfo?vid=";

    @Override
    protected Request getStartRequest(JSONObject target)
    {
        return new Request("http://so.mgtv.com/so/k-"
                + KeywordEncode.encode(target.getString("tvName")));
    }

    @Override
    public String getPageDataType(Page page)
    {
        String url = page.getUrl().toString();
        if (url.contains("http://so.mgtv.com/so/k-"))
            return Constants.PageDataType.SEARCH_LIST;
        else if (url.contains("http://vc.mgtv.com/v2/dynamicinfo"))
            return Constants.PageDataType.TV_RECORD;
        else
            return Constants.PageDataType.TV_COMMENT;
    }

    @Override
    public void process(Page page)
    {
        Map<String, Object> tvMap = page.getRequest().getExtras();
        switch (this.getPageDataType(page))
        {
            case Constants.PageDataType.SEARCH_LIST:
                this.searchListProcess(page, tvMap);
                break;
            case Constants.PageDataType.TV_RECORD:
                this.tvRecordProcess(page, tvMap);
                break;
            case Constants.PageDataType.TV_COMMENT:
                this.commentProcess(page, tvMap);
                break;
            default:
                break;
        }
    }

    private void searchListProcess(Page page, Map<String, Object> tvMap)
    {
        List<String> divList = page.getHtml()
                .xpath("//div[@class='search-resultlist']/div[@class='so-result-info']")
                .all();
        if (divList == null || divList.isEmpty())
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);

        List<String> nameList = new ArrayList<String>();
        List<String> tvTypeList = new ArrayList<String>();
        List<List<String>> dirList = new ArrayList<List<String>>();
        List<List<String>> actList = new ArrayList<List<String>>();
        List<String> linkList = new ArrayList<String>();
        final List<String> tvIdList = new ArrayList<String>();

        for (String divStr : divList)
        {
            Html divObj = new Html(divStr);
            String  yugaop = divObj.xpath("//p[@class='result-pic']//a//span[@class='info']/text()").get(); //预告片
            if(yugaop !=null && yugaop.equals("预告")){
            	continue;
            }
            
            String name = divObj.xpath("//p[@class='result-til']//a").get();
            name = StringUtils.isEmpty(name) ? divObj.xpath("//div[@class='tele_hd']//b").get() :
                    name;
            nameList.add(name == null ? null : StringUtils.trim(HtmlUtil.delHTMLTag(name)));

            List<String> pList = divObj.xpath("//p[@class='text-1']").all();
            String directors = this.getTVAttr(pList, "导演");
            directors = StringUtils.isEmpty(directors) ? StringUtils.join(divObj.xpath
                    ("//div[@class='info_item']//a/text()").all(), SepratorUtil.SEP_COMMA_EN) :
                    directors;
            dirList.add(directors == null ? null
                    : Arrays.asList(
                    directors.split(SepratorUtil.SEP_COMMA_EN)));

            String actors = this.getTVAttr(pList, "主演");
            actors = StringUtils.isEmpty(actors) ? StringUtils.join(divObj.xpath
                    ("//div[@class='info_item']//a/text()").all(), SepratorUtil.SEP_COMMA_EN) :
                    actors;
            actList.add(actors == null ? null
                    : Arrays.asList(actors.split(SepratorUtil.SEP_COMMA_EN)));

            tvTypeList.add(this.getTVType(divObj, pList));
            String link = divObj.xpath("p[@class='result-pic']/a/@href").get();
            link = StringUtils.isEmpty(link) ? divObj.xpath("//div[@class='vari_pho']/a/@href").get
                    () : link;
            linkList.add(link);
            String tvId = divObj.xpath("p[@class='result-pic']/a/@clip-id").get();
            tvId = StringUtils.isEmpty(tvId) ? divObj.xpath("//div[@class='vari_pho']/a/@clip-id")
                    .get() : tvId;
            tvIdList.add(tvId);
            //获取上映时间
            String firstTime = divObj.xpath("//p[@class='result-til']/span[@class='year']/text()").toString();
            if(StringUtil.isNotEmpty(firstTime)){
            	firstTime = firstTime.replaceAll("上映时间:", "");
            	tvMap.put("firstTime", firstTime);
            }
            //获取评分
            String score = divObj.xpath("//p[@class='result-til']/span[@class='score']/text()").toString();
            if(StringUtil.isNotEmpty(firstTime)){
            	tvMap.put("score", score);
            }
        }

        TVProcessUtils.addTVFromSearchList(page, tvMap, nameList, linkList,
                tvTypeList, actList, dirList, new TVProcessUtils.TVMatcher()
                {
                    @Override
                    protected boolean addTV(Page page,
                            Map<String, Object> tvMap, String name,
                            String tvType, List<String> pageActors,
                            List<String> pageDirector, String link, int idx)
                    {
                        if (TVProcessUtils.tvMatched(tvMap, name,
                                TVProcessUtils.getTVType(tvType), pageActors,
                                pageDirector)
                                && link.contains("www.mgtv.com"))
                        {
                            PageUtils.addTargetRequest(page,
                                    "http://vc.mgtv" +
                                            ".com/v2/dynamicinfo?callback" +
                                            "=jQuery182023383393051521595_1492573970097&cid="
                                            + tvIdList.get(idx)
                                            + "&_=1492573970304",
                                    tvMap, true);// 播放量

                            PageUtils.addTargetRequest(page,
                                    "http://comment.mgtv" +
                                            ".com/video_comment/list/?callback" +
                                            "=jQuery182023383393051521595_1492573970098&"
                                            + "type=hunantvcollection&subject_id="
                                            + tvIdList.get(idx)
                                            + "&page=1&_=1492573970255",
                                    tvMap);// 评论
                            return true;
                        }
                        return false;
                    }
                }, this.getGetter(divList));
    }

    /**
     * 设置已更新集次
     */
    private TVProcessUtils.UpdateSetGetter getGetter(final List<String> divList)
    {
        final String tag = "<b style=\"background-color:#07B85A\">新</b>";

        return new TVProcessUtils.UpdateSetGetter()
        {
            @Override
            public String getUpdateSet(int idx)
            {
                Html divObj = new Html(divList.get(idx));
                List<String> aList = divObj.xpath("//a[@class='report-click']")
                        .all();
                if (aList == null || aList.isEmpty())
                    return null;
                for (String aStr : aList)
                {
                    if (aStr.contains(tag))
                    {
                        String set = new Html(aStr).xpath("//a/text()").get();
                        set = set == null ? StringUtils.EMPTY : set.trim();
                        if (RegexUtils.regexMatch(RegexUtils.REGEX_INTEGER,
                                set))
                            return (Integer.parseInt(set) - 1) + "";
                        else
                            break;
                    }
                }
                return null;
            }
        };
    }

    /**
     * 获取电视剧的属性
     *
     * @param pList 页面元素类别
     * @param label 属性标识，如：导演、主演
     * @return 属性值
     */
    private String getTVAttr(List<String> pList, String label)
    {
        if (pList == null || pList.isEmpty())
            return null;
        for (String pStr : pList)
        {
            if (!pStr.contains(label))
                continue;
            return StringUtils.join(new Html(pStr).xpath("//a/text()").all(),
                    SepratorUtil.SEP_COMMA_EN);
        }
        return null;
    }

    /**
     * 获取作品类型
     *
     * @param divObj 页面元素
     * @param pList  属性元素类别
     * @return 作品类型：如电视剧、电影
     */
    private String getTVType(Html divObj, List<String> pList)
    {
        String type = this.getTVAttr(pList, "类型");
        if (StringUtils.isNotEmpty(type))
            return type;
        type = this.getTVAttr(divObj.xpath("//div[@class='info_it']").all(),
                "类型");
        if (StringUtils.isNotEmpty(type))
            return type;
        String classStr = divObj.xpath("//div[@class='so-result-info']/@class")
                .get();
        if (StringUtils.isNotEmpty(classStr))
        {
            String classTag = RegexUtils
                    .regexSearch("search-movie|search-television", classStr);
            if (StringUtils.isNotEmpty(classTag))
            {
                switch (classTag)
                {
                    case "search-television":
                        return "电视剧";
                    case "search-movie":
                        return "电影";
                    default:
                        break;
                }
            }
        }
        return null;
    }

    private void tvRecordProcess(Page page, Map<String, Object> tvMap)
    {
        String res = page.getRawText();
        if (StringUtils.isEmpty(res))
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);
        res = RegexUtils.regexSearch("\"all\":" + RegexUtils.REGEX_INTEGER,
                res);
        if (StringUtils.isEmpty(res))
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);
        res = RegexUtils.regexSearch(RegexUtils.REGEX_INTEGER, res);

        page.putField(TVRecordModel.class.getName(),
                new TVRecordModel(tvMap.get("tvid") + "",
                        TVProcessUtils.getPageTVName(tvMap),
                        Constants.SiteName.MGTV, tvMap.get("score")+"", res, null, null, null,
                        null, TVProcessUtils.getPageUpdateSet(tvMap),tvMap.get("firstTime") + ""));
    }

    private void commentProcess(Page page, Map<String, Object> tvMap)
    {
        String commentsJsonStr = page.getRawText();
        if (StringUtils.isEmpty(commentsJsonStr))
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);

        int start = commentsJsonStr.indexOf(SepratorUtil.SEP_LEFT_PARENTHESES);
        int end = commentsJsonStr
                .lastIndexOf(SepratorUtil.SEP_RIGHT_PARENTHESES);
        if (start < 0 || end < 0 || end < start)
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);
        commentsJsonStr = commentsJsonStr.substring(
                start + SepratorUtil.SEP_LEFT_PARENTHESES.length(), end);

        JSONObject resObj = JSONObject.fromObject(commentsJsonStr);
        if (resObj == null || resObj.isEmpty() || !resObj.has("comments"))
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);

        JSONArray commentArray = JSONObject.fromObject(commentsJsonStr)
                .getJSONArray("comments");
        if (commentArray.size() < 1)
            throw new SpiderException(
                    SpiderExceptionCode.DataInvalideException);

        List<TVPubCommentModel> commentList = new ArrayList<TVPubCommentModel>();
        for (int i = 0; i < commentArray.size(); i++)
        {
            JSONObject comment = commentArray.getJSONObject(i);
            commentList.add(new TVPubCommentModel(tvMap.get("tvid") + "",
                    tvMap.get("tvName") + "", Constants.SiteName.MGTV,
                    comment.getJSONObject("user").getString("nickname"),
                    comment.getString("content"),
                    comment.getString("create_time"), null,
                    page.getUrl().toString()));
        }
        page.putField(TVPubCommentModel.class.getName(), commentList);
    }

    @Override
    protected String getSpiderType()
    {
        return Constants.SpiderTaskType.TV_MGTV;
    }
}